#!/bin/bash
# Copyright 2024-2025 Mengning Software All rights reserved.

# 用于编译客户机指定多用户共享目录
DATA_DISK="/datadisk"
SHARE_DIR="aosp14"
# 用于Executor挂载AOSP prebuilts 编译环境
# AOSP_NFS_IP=192.168.1.4 # NFS服务器IP地址
AOSP_PREBUILTS_PATH=$DATA_DISK/$SHARE_DIR/prebuilts # 与NFS服务器配置的共享路径相同，比如/datadisk/aosp14/prebuilts

# Exit immediately if a command exits with a non-zero status
set -e
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# Function to display success message
function success {
  echo -e "${GREEN}$1${NC}"
}

# Function to display failure message
function failure {
  echo -e "${RED}$1${NC}"
}

usage() { 
	success "Copyright 2024-2025 Mengning Software All rights reserved.\n";
	success ">>>>Welcome to use the CloudBuild<<<<\n";
    failure "Usage: $0 [OPTION]..."  
    echo ""  
    success "Options:"  
    success "  -h, --help          			Show this help message and exit"  
    success "  --clean             			Clean up temporary files"  
    success "  --easy [AOSP_PATH]  			Easy way to install client and server."  
    success "                      			If it is an AOSP project, the root directory of the AOSP project needs to be specified." 
    success "                      			example: --easy /home/USER_NAME/$SHARE_DIR"  
    success "  -c [AOSP_PATH]      			Install CloudBuild client. " 
    success "                      			If it is an AOSP project, the root directory of the AOSP project needs to be specified." 
    success "                      			example: -c $DATA_DISK/$SHARE_DIR"  
    success "  -s [REDIS_IP]        			Install CloudBuild server. "
    success "                      			If there is a standalone Redis server as the cache server, "
	success "                      			the IP address of the Redis server needs to be specified." 
    success "  -e SERVER_IP [NFS_IP]      		Install CloudBuild executor."
 	success "                      			It is necessary to specify the IP address of the CloudBuild server. "
    success "                      			If it is an AOSP project, the IP address of the NFS server must also be specified." 
    success "  --adduser [USER_NAME]			add a user and make all users share $DATA_DISK/$SHARE_DIR as /home/USER_NAME/$SHARE_DIR."  
    success "                      			example: --adduser mengning" 
    echo ""  
    exit 0  
} 

# Function to clean build directory
function clean {
	sudo docker rm -f master;
	sudo docker rm -f executor;
	sudo docker volume rm -f nfs;
	sudo rm -rf $HOME/.CloudBuild 
	success "clean up！"
}

# Detect the OS type and install dependencies
function install_dependencies {
  # Install dependencies based on the OS type
  success "dependencies install begin: " 
  OS_ID=$(grep '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"')

  case $OS_ID in
    ubuntu|debian)
		# 检查 Docker 是否已安装  
		if ! command -v docker &> /dev/null  
		then  
			echo "Installing Docker..."  
			# 更新包索引  
			sudo apt-get update  
			# 安装 Docker  
			sudo apt-get install -y docker.io 
			success "Docker Installed！"  
		else  
			success "Docker Installed, $(docker --version)"  
		fi
      ;;
    centos)
    #   sudo yum update -y
    #   sudo yum install -y epel-release
    #   sudo yum groupinstall -y "Development Tools"
    #   sudo yum install -y git cmake3 gtest gtest-devel openssl openssl-devel pkgconfig uuid-devel grpc-devel protobuf protobuf-devel protobuf-compiler ninja-build yaml-cpp yaml-cpp-devel
      ;;
    fedora)
    #   sudo dnf update -y
    #   sudo dnf group install -y "Development Tools"
    #   sudo dnf install -y git cmake g++ gtest gtest-devel openssl openssl-devel pkgconfig uuid-devel grpc-devel protobuf protobuf-devel protobuf-compiler ninja-build yaml-cpp yaml-cpp-devel
      ;;
    *)
      failure "Unsupported OS: $OS_ID"
      exit 1
      ;;
  esac
}

# Function to install the built ninja binary
function android_ninja_install {
  wget -c https://gitee.com/cloudbuild888/cloudbuild/releases/download/v1.0/android_ninja.tar.gz
  tar -zxvf android_ninja.tar.gz
  local install_path="/usr/bin/ninja"
  local backup_path="/usr/bin/ninja.prev"
  local config_file="$HOME/.ninja2.conf"

  # Backup existing ninja if it exists
  if [ -f "$install_path" ]; then
    sudo mv "$install_path" "$backup_path"
    success "Backed up original ninja to $backup_path"
  fi

  # Install new ninja binary
  sudo cp "ninja2/ninja" "$install_path"
  if [ ! -f "$config_file" ]; then
	cp "ninja2/.ninja2.conf" "$config_file"
  fi
  sudo cp -n ninja2/*.so.* /usr/local/lib/
  sudo ldconfig
}

deploy_ninja() {
	aosp_path=$1
	echo "start deploying ninja2..."
	if [ $aosp_path ]; then
		echo aosp_path:$aosp_path
		# 检查 nfs-kernel-server 是否已安装  
		if ! dpkg -l | grep -q nfs-kernel-server; then  
			echo "nfs-kernel-server 没有安装，正在安装..."  
			sudo apt-get install -y nfs-kernel-server  
		else  
			echo "nfs-kernel-server 已经安装。"  
		fi
		# 定义要添加的行  
		LINE="$aosp_path/prebuilts *(rw,root_squash,anonuid=1000,anongid=1000,insecure,async,no_subtree_check)"  
		# 检查 /etc/exports 是否已经包含该行  
		if ! grep -qF "$LINE" /etc/exports; then
			sudo sed -i '/^[^#]/d' /etc/exports # 删除已有的配置信息  
			echo "$LINE" | sudo tee -a /etc/exports > /dev/null
		fi 
		sudo systemctl restart nfs-kernel-server;
		success "NFS Server Started."
		(cd $aosp_path/prebuilts/build-tools/linux-x86/bin &&
			if [ -L ninja ]; then
				rm -rf ninja android_ninja
			else
				mv ninja prebuilts-ninja
			fi 
		)
		android_ninja_install
		sudo cp -n ${PWD}/.cloudbuild.yml $aosp_path/
		sudo cp -n ${PWD}/.ninja2.conf $aosp_path/
		sudo cp ${PWD}/ninja2/ninja $aosp_path/prebuilts/build-tools/linux-x86/bin/android_ninja
		(cd $aosp_path/prebuilts/build-tools/linux-x86/bin && ln -s android_ninja ninja)
		sed -i '/cmd.Sandbox = ninjaSandbox/s/^/\/\//' $aosp_path/build/soong/ui/build/ninja.go
		sudo rm -rf ninja2
		success "---------------------------------"
		success "New Ninja2 for AOSP installed successfully at $aosp_path/prebuilts/build-tools/linux-x86/bin/android_ninja"
		success "---------------------------------"
  		success "Copyright 2024 Mengning Software All rights reserved."
	else
		wget -c https://raw.githubusercontent.com/ninja-cloudbuild/ninja2/refs/heads/main/install.sh && chmod +x install.sh && sudo ./install.sh
    fi
}

deploy_server(){
	redis_ip="$1"
	echo "start deploying server..."
	server_image="devstar.cn/mengning/cloudbuild-master:1.0"
	if [ -z "$redis_ip" ]; then  
		redis_ip=$(ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tail -n 1 | xargs)
		
		if [ ! -f "/etc/redis/redis.conf" ]; then
			sudo apt-get -y install redis
		fi
		(cd /etc/redis &&
			sudo sed -i "69c bind 127.0.0.1 $redis_ip  ::1" redis.conf &&
			sudo sed -i "92c port 9527" redis.conf)
		sudo systemctl restart redis
		success "Redis started in $redis_ip:9527"
	fi 
			
	if [ ! -z $redis_ip ]; then
		sudo docker pull $server_image

		if [ ! -d "$HOME/.CloudBuild" ]; then
			mkdir -p ~/.CloudBuild
		fi

		(cd ~/.CloudBuild &&
		if [ ! -f "server.yaml" ]; then
			echo "app:
  no_default_user_group: true
  create_group_per_user: true
  add_user_to_domain_group: true
  code_editor_enabled: true
  default_redis_target: \"$redis_ip:9527\"
  enable_target_tracking: true
database:
  data_source: \"sqlite3:///tmp/buildbuddy-enterprise.db\"
#olap_database:
#data_source: \"clickhouse://default:@127.0.0.1:9000/buildbuddy_local\"
storage:
  ttl_seconds: 86400 # One day in seconds.
  disk:
    root_directory: /tmp/buildbuddy_enterprise
cache:
  redis:
    redis_target: \"$redis_ip:9527\"
  disk:
    root_directory: /tmp/buildbuddy-enterprise-cache
auth:
  enable_anonymous_usage: true
  enable_self_auth: true" >server.yaml
		else
			sed -i "6c   \ \ default_redis_target: \"$redis_ip:9527\"" ~/.CloudBuild/server.yaml
			sed -i "18c   \ \ \ \ redis_target: \"$redis_ip:9527\"" ~/.CloudBuild/server.yaml
		fi )
	fi

	if [ ! -f "$HOME/.CloudBuild/server.yaml" ]; then
		echo "please deploy the server first!"
		exit -1
	fi

	sudo docker run -it --name master -p 1985:1985 -p 8080:8080 -v ~/.CloudBuild/server.yaml:/config.yaml $server_image
}

deploy_executor(){
	server_ip="$1"
	AOSP_NFS_IP="$2"
	echo "start deploying executor..."
	echo server_ip:$server_ip AOSP_NFS_IP:$AOSP_NFS_IP
	executor_image="devstar.cn/mengning/cloudbuild-executor:1.0"
	if [ ! -z $server_ip ]; then
		sudo docker pull $executor_image

		if [ ! -d "$HOME/.CloudBuild" ]; then
			mkdir -p ~/.CloudBuild
		fi
		(cd ~/.CloudBuild &&
		if [ ! -f "executor.yaml" ]; then
			echo "executor:
  root_directory: \"/tmp/remote_build\"
  docker_socket: \"\"
  docker_inherit_user_ids: false
  enable_firecracker: false
  app_target: \"grpc://$server_ip:1985\"
  local_cache_directory: \"/tmp/filecache\"
  local_cache_size_bytes: 10000000000 # 10GB" >executor.yaml

		else
			sed -i "6c   \ \ app_target: \"grpc://$server_ip:1985\"" ~/.CloudBuild/executor.yaml
		fi )
	fi

	if [ ! -f "$HOME/.CloudBuild/executor.yaml" ]; then
		echo "please deploy the executor first!"
		exit -1
	fi
	
	if [ ! -z $AOSP_NFS_IP ]; then
		echo server_ip:$server_ip AOSP_NFS_IP:$AOSP_NFS_IP
		# 检查 nfs-common 是否已安装  
		if ! dpkg -l | grep -q nfs-common; then  
			echo "nfs-common 没有安装，正在安装..."  
			sudo apt-get install -y nfs-common  
		else  
			echo "nfs-common 已经安装。"  
		fi
		sudo docker volume create --driver local --opt type=nfs --opt o=addr=$AOSP_NFS_IP,rw --opt device=:$AOSP_PREBUILTS_PATH --name nfs
		sudo docker run -e HOME=/app/ -it --name executor -v ~/.CloudBuild/executor.yaml:/config.yaml -v nfs:/app/prebuilts $executor_image
	else
		sudo docker run -it --name executor -v ~/.CloudBuild/executor.yaml:/config.yaml $executor_image
	fi
}

adduser(){
	username="$1"
	# 检查用户是否已存在  
	if ! id "$username" &>/dev/null; then  
		echo "正在创建用户 $username..."  
		# 创建用户  
		sudo useradd -m "$username"  	
		# 设置用户密码 (提示输入)  
		sudo passwd "$username"  	
		echo "用户 $username 创建成功。"  
	fi 
 
	# 检查目录是否存在  
	if [ ! -d "$DATA_DISK" ]; then  
		sudo mkdir -p "$DATA_DISK"  
		# 腾讯云测试专用代码，在用户环境下可能会误触发，用户创建好datadisk目录则不会触发
		DEVICE="/dev/vdb" 
		if [ -e "$DEVICE" ]; then
			sudo mount "$DEVICE" "$DATA_DISK"
			sudo resize2fs "$DEVICE"		
			if [ -d "$DATA_DISK/aosp14_new" ]; then
				(cd "$DATA_DISK" && mv aosp14_new $SHARE_DIR && sudo rm -rf OpenHarmony-v4.1-Release)
			fi
		fi
	fi
	mkdir -p "$DATA_DISK/$username"
	mkdir -p "$DATA_DISK/$username/my_data"
	mkdir -p "$DATA_DISK/$username/tmp_data"	
	sudo mkdir -p "/home/$username/$SHARE_DIR"
	sudo mount -t overlay overlay -o lowerdir="$DATA_DISK/$SHARE_DIR",upperdir="$DATA_DISK/$username/my_data",workdir="$DATA_DISK/$username/tmp_data" "/home/$username/$SHARE_DIR"
}

while getopts "hs:c:e: -- -" opt; do 
	case "$1" in  
		--help|-h)  
            usage  
			shift 
			break  
			;;  
		--clean)  
			clean  
			shift 
			break  
			;; 
		--client|-c)  
			aosp_path="$2"
			deploy_ninja $aosp_path  
			shift 1  
			break
			;;  
		--server|-s)  
			redis_ip="$2"  
			install_dependencies  
			deploy_server $redis_ip  
			shift 1  
			break
			;;  
		--executor|-e)  
			server_ip="$2"  
			nfs_ip="$3"
			install_dependencies  
			deploy_executor $server_ip $nfs_ip
			shift 2
			break
			;;  
		--easy)  
			echo "easy mode"  
			aosp_path="$2" 
			install_dependencies
			deploy_ninja $aosp_path  
			deploy_server  
			shift 1
			break 
			;;  
		--adduser)  
			echo "adduser $2"  
			username="$2"  
			adduser $username  
			shift 1
			break
			;;  
		-|--)  
			failure "Please enter the correct parameters."  
			usage  
			shift  
			break  
			;;  

	esac  
done
